package dao

import (
	"fmt"
	"gc-rds-ha/internal/common"
	"time"

	log "github.com/sirupsen/logrus"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var (
	//DB 数据库实例
	DB          *gorm.DB
	DB_PROXYSQL *gorm.DB
	//DB_SANDBOX *gorm.DB
	//DB_TEST    *gorm.DB
	dbConfigs = map[string]databaseConfig{
		"proxysql": {
			dsn: fmt.Sprintf("%s:%s@tcp(%s:%d)/?charset=utf8mb4&parseTime=True&loc=Local&timeout=3s",
				common.AgentConfig.ProxySql.User,
				common.AgentConfig.ProxySql.Pwd,
				common.AgentConfig.ProxySql.Ip,
				common.AgentConfig.ProxySql.Port,
			),
		},
		"mysql": {
			dsn: fmt.Sprintf("%s:%s@tcp(%s:%d)/?charset=utf8mb4&parseTime=True&loc=Local&timeout=3s",
				common.AgentConfig.Mysql.User,
				common.AgentConfig.Mysql.Pwd,
				common.AgentConfig.Mysql.Ip,
				common.AgentConfig.Mysql.Port,
			),
		},
	}
	err error
)

type databaseConfig struct {
	dsn string
}

type DefaultField struct {
	ID        int       `gorm:"AUTO_INCREMENT;primaryKey"`
	CreatedAt time.Time `gorm:"type:datetime(3);comment:创建时间"`
	UpdatedAt time.Time `gorm:"type:datetime(3);comment:更新时间"`
}

type SelectDb struct {
	DB *gorm.DB
}

func init() {
	openMysql()
}

func openMysql() {
	if c, ok := dbConfigs["mysql"]; ok {
		DB = newDB(c.dsn)
		s := SelectDb{
			DB: DB,
		}
		DB = s.Connect(common.AgentConfig.Mysql.DbName, true)
	}
	if c, ok := dbConfigs["proxysql"]; ok && common.AgentConfig.ProxySql.Open {
		DB_PROXYSQL = newDB(c.dsn)
		s := SelectDb{
			DB: DB_PROXYSQL,
		}
		DB_PROXYSQL = s.Connect("main", true)
	}
}

func (db SelectDb) Connect(dbName string, autoCreate bool) *gorm.DB {
	if autoCreate {
		createDatabaseSql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", dbName)
		if err = db.DB.Exec(createDatabaseSql).Error; err != nil {
			log.WithField("error:", log.Fields{
				"createDatabaseSql": createDatabaseSql,
				"error":             err,
			}).Fatalf("create database %s failed!", common.AgentConfig.Mysql.DbName)
		}
	}

	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		common.AgentConfig.Mysql.User,
		common.AgentConfig.Mysql.Pwd,
		common.AgentConfig.Mysql.Ip,
		common.AgentConfig.Mysql.Port,
		dbName,
	)
	return newDB(dsn)
}

func newDB(dsn string) *gorm.DB {
	db, err := gorm.Open(mysql.New(mysql.Config{
		DSN: dsn,
	}), &gorm.Config{})
	if err != nil {
		log.WithField("error:", log.Fields{
			"mysql": dsn,
			"error": err,
		}).Fatal("connect mysql failed!")
	}

	if common.AgentConfig.Debug {
		db = db.Debug()
	}
	return db
}
